package com.cah.game;

import java.io.IOException;

import org.json.JSONException;
import org.json.JSONObject;

import com.cah.library.UserFunctions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;

import android.app.ActionBar;
import android.app.Activity;
import android.app.Dialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;

public class MainActivity extends Activity
{
	protected String userKey;
	FragmentManager fragmentManager;
	GoogleCloudMessaging gcm;
	String regid;
	String SENDER_ID = "893332552528";
	ActionBar actionBar;
	int currentParent = -1;
	String currentGameKey, currentGameName;
	boolean historyForwardVisible = false, historyBackVisible = false;
	
	private static final String FRAG_TAG = "cahFragTag";
	private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
	public static final String PROPERTY_REG_ID = "registration_id";
    private static final String PROPERTY_APP_VERSION = "appVersion";
	private final String TAG = "GCM";
	private final static int LOBBY = 0;
	private final static int PENDING_GAME_LIST = 1;
	private final static int GAME = 2;
	float scale = 0f;
	
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		userKey = getIntent().getStringExtra("userKey");
		
		actionBar = getActionBar();
		
		scale = getResources().getDisplayMetrics().density;
		
		if(checkPlayServices())
		{
			gcm = GoogleCloudMessaging.getInstance(this);
            regid = getRegistrationId(getApplicationContext());
            
            if (regid.isEmpty()) 
            {
                new RegisterIDProcess().execute();
            }
            
		}
		else
		{
			Dialog dialog = GooglePlayServicesUtil.getErrorDialog(ConnectionResult.SERVICE_MISSING, this, 0);
			dialog.show();
		}
		
		fragmentManager = getFragmentManager();
		
		if(savedInstanceState == null)
		{
			Intent intent = getIntent();
			
			if(intent.getStringExtra("gameKey") == null)
			{
				//Start the app off in the lobby
				FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
				LobbyFragment fragment = new LobbyFragment();
				fragmentTransaction.add(android.R.id.content, fragment, FRAG_TAG);
				fragmentTransaction.commit();
				
				currentParent = LOBBY;
				currentGameKey = "";
				currentGameName = "";

			}
			else
			{
				startGameFragment(intent.getStringExtra("gameKey"), 1);
			}
		}
		else
		{
			currentParent = savedInstanceState.getInt("currentParent");
			currentGameKey = savedInstanceState.getString("currentGameKey");
			currentGameName = savedInstanceState.getString("currentGameName");
			historyBackVisible = savedInstanceState.getBoolean("historyBackVisible");
			historyForwardVisible = savedInstanceState.getBoolean("historyForwardVisible");
			
			FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
			Fragment fragment = fragmentManager.findFragmentByTag(FRAG_TAG);
			fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
			fragmentTransaction.commit();
		}
	}
	
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);
		outState.putInt("currentParent", currentParent);
		outState.putString("currentGameKey", currentGameKey);
		outState.putString("currentGameName", currentGameName);
		outState.putBoolean("historyForwardVisible", historyForwardVisible);
		outState.putBoolean("historyBackVisible", historyBackVisible);
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    // Handle presses on the action bar items
	    switch (item.getItemId()) {
	        case android.R.id.home:
	            this.startParentFragment();
	            return true;
	        case R.id.action_logout:
	        	Intent intent = new Intent(this, LoginActivity.class);
	        	startActivity(intent);
	        	finish();
	        	return true;
	        case R.id.action_create_game:
	        	this.startCreateGameFragment();
	        	return true;
	        case R.id.action_join_game:
	        	this.startPendingGameListFragment();
	        	return true;
	        case R.id.action_back:
	        	GameHistoryFragment fragment = (GameHistoryFragment)(fragmentManager.findFragmentByTag(FRAG_TAG));
	        	this.startGameHistoryFragment(fragment.getGameKey(), fragment.getGameStatus(), fragment.getRoundEnd() - 10);
	        	return true;
	        case R.id.action_forward:
	        	GameHistoryFragment fragment2 = (GameHistoryFragment)(fragmentManager.findFragmentByTag(FRAG_TAG));
	        	this.startGameHistoryFragment(fragment2.getGameKey(), fragment2.getGameStatus(), fragment2.getRoundEnd() + 10);
	        	return true;
	        default:
	            return super.onOptionsItemSelected(item);
	    }
	}
	
	public void startCreateGameFragment()
	{
		CreateGameFragment fragment = new CreateGameFragment();
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
		fragmentTransaction.commit();
		
		
		
		currentParent = LOBBY;
	}
	
	public void startPendingGameListFragment()
	{
		PendingGameListFragment fragment = new PendingGameListFragment();
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
		fragmentTransaction.commit();
		
		currentParent = LOBBY;
	}
	
	public void startPendingGameFragment(String gameKey)
	{
		PendingGameFragment fragment = new PendingGameFragment(gameKey);
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
		fragmentTransaction.commit();
		
		
		
		currentGameKey = gameKey;
		currentParent = PENDING_GAME_LIST;
	}
	
	public void startGameFragment(String gameKey, int gameStatus)
	{
		
		if(gameStatus==0)
		{
			startPendingGameFragment(gameKey);
		}
		else if(gameStatus==2)
		{
			startGameHistoryFragment(gameKey, gameStatus, -1);
		}
		else
		{
			currentParent = LOBBY;
			currentGameKey = gameKey;
			
			GameFragment fragment = new GameFragment(gameKey);
			FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
			fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
			fragmentTransaction.commit();
		}
			
	}
	
	public void startGameHistoryFragment(String gameKey, int gameStatus, int roundEnd)
	{
		GameHistoryFragment fragment = new GameHistoryFragment(gameKey, gameStatus, roundEnd);
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
		fragmentTransaction.commit();
				
		if(gameStatus==1)
		{
			currentGameKey = gameKey;
			currentParent = GAME;
		}
		else if(gameStatus==2)
		{
			currentParent = LOBBY;
		}
		
		
	}
	
	public void startLobbyFragment()
	{
		LobbyFragment fragment = new LobbyFragment();
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
		fragmentTransaction.commit();
		
		
		currentParent = LOBBY;
	}
	
	public void startGameCzarFragment(String gameKey, JSONObject gameInfo)
	{
		GameCzarFragment fragment = new GameCzarFragment(gameKey, gameInfo);
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
		fragmentTransaction.commit();
	}
	
	public void startGameNotCzarFragment(String gameKey, JSONObject gameInfo)
	{
		GameNotCzarFragment fragment = new GameNotCzarFragment(gameKey, gameInfo);
		FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
		fragmentTransaction.replace(android.R.id.content, fragment, FRAG_TAG);
		fragmentTransaction.commit();
	}
	
	public void startParentFragment()
	{
		switch (currentParent)
		{
			case LOBBY:
				startLobbyFragment();
				break;
			case GAME:
				startGameFragment(currentGameKey, 1);
				break;
			case PENDING_GAME_LIST:
				startPendingGameListFragment();
				break;
		}
	}
	
	public String getUserKey()
	{
		return userKey;
	}
	
	protected void onResume() 
	{
	    super.onResume();
	    checkPlayServices();
	}
	
	
	private boolean checkPlayServices()
	{
		int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
	    if (resultCode != ConnectionResult.SUCCESS) {
	        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
	            GooglePlayServicesUtil.getErrorDialog(resultCode, this,
	                    PLAY_SERVICES_RESOLUTION_REQUEST).show();
	        } else {
	            Log.i(TAG, "This device is not supported.");
	            finish();
	        }
	        return false;
	    }
	    return true;
	}
	
	private class RegisterIDProcess extends AsyncTask<Void, Void, JSONObject>
	{

		protected JSONObject doInBackground(Void... params) {
			UserFunctions uf = new UserFunctions(userKey);
            Context context = getApplicationContext();
            JSONObject json = null;
            try {
                if (gcm == null) {
                    gcm = GoogleCloudMessaging.getInstance(context);
                }
                regid = gcm.register(SENDER_ID);

                // You should send the registration ID to your server over HTTP,
                // so it can use GCM/HTTP or CCS to send messages to your app.
                // The request to your server should be authenticated if your app
                // is using accounts.
                json = uf.registerUserDevice(regid);

                // For this demo: we don't need to send it because the device
                // will send upstream messages to a server that echo back the
                // message using the 'from' address in the message.

            } catch (IOException ex) {
            	Log.e(TAG, ex.getMessage());
                // If there is an error, don't just keep trying to register.
                // Require the user to click a button again, or perform
                // exponential back-off.
            }
            return json;
        }

		protected void onPostExecute(JSONObject json)
		{
			try
			{
				if(json.getInt("success")==1)
				{
					storeRegistrationId(getApplicationContext(), regid);
				}
			} catch (JSONException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	private void storeRegistrationId(Context context, String regId) {
	    final SharedPreferences prefs = getGCMPreferences(context);
	    int appVersion = getAppVersion(context);
	    Log.i(TAG, "Saving regId on app version " + appVersion);
	    SharedPreferences.Editor editor = prefs.edit();
	    editor.putString(PROPERTY_REG_ID, regId);
	    editor.putInt(PROPERTY_APP_VERSION, appVersion);
	    editor.commit();
	}
	
	private static int getAppVersion(Context context) {
	    try {
	        PackageInfo packageInfo = context.getPackageManager()
	                .getPackageInfo(context.getPackageName(), 0);
	        return packageInfo.versionCode;
	    } catch (NameNotFoundException e) {
	        // should never happen
	        throw new RuntimeException("Could not get package name: " + e);
	    }
	}
	
	private SharedPreferences getGCMPreferences(Context context) {
	    // This sample app persists the registration ID in shared preferences, but
	    // how you store the regID in your app is up to you.
	    return getSharedPreferences(MainActivity.class.getSimpleName(),
	            Context.MODE_PRIVATE);
	}
	
	private String getRegistrationId(Context context) {
	    final SharedPreferences prefs = getGCMPreferences(context);
	    String registrationId = prefs.getString(PROPERTY_REG_ID, "");
	    if (registrationId.isEmpty()) {
	        Log.i(TAG, "Registration not found.");
	        return "";
	    }
	    // Check if app was updated; if so, it must clear the registration ID
	    // since the existing regID is not guaranteed to work with the new
	    // app version.
	    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
	    int currentVersion = getAppVersion(context);
	    if (registeredVersion != currentVersion) {
	        Log.i(TAG, "App version changed.");
	        return "";
	    }
	    return registrationId;
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) 
	{
	    // Inflate the menu items for use in the action bar
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.action_bar, menu);
	    
	    MenuItem backButton = menu.findItem(R.id.action_back);
	    backButton.setVisible(historyBackVisible);
	    MenuItem forwardButton = menu.findItem(R.id.action_forward);
	    forwardButton.setVisible(historyForwardVisible);
	    
	    return super.onCreateOptionsMenu(menu);
	}
	
	public void log(String message)
	{
		Log.e("cah", message);
	}
	
	public int pxToDp(int px)
	{
		float scale = getResources().getDisplayMetrics().density;
		return (int)(px*scale + 0.5f);
	}
}
